package com.lzq.framework.util.time;

import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import java.text.ParseException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;

/**
 * @author 2019/3/21 15:13 by 刘赵强
 **/
public class DateUtil {
    public static final String YYYYMMDDHHMMSS = "yyyy-MM-ddHHmmss";
    public static final String YYYYMMDDHH_MM_SS = "yyyy-MM-dd HH:mm:ss";
    public static final String YYYYMMDD = "yyyy-MM-dd";
    private static final Logger LOGGER = LoggerFactory.getLogger(DateUtil.class);
    private static final String DEFAULT_PATTERN = "yyyy-MM-dd";
    private static final String DEFAULT_PATTERN_YEAR = "yyyy";
    private static final long DAY_MILLIS = 86400000L;
    private static final long HOUR_MILLIS = 3600000L;
    private static final long MINUTE_MILLIS = 60000L;

    public DateUtil() {
    }

    public static Date getCurrentDate() {
        return new Date(System.currentTimeMillis());
    }

    public static Date getCurrentDateNoTime() {
        Calendar cal = Calendar.getInstance();
        cal.set(10, 0);
        cal.set(12, 0);
        cal.set(13, 0);
        cal.set(14, 0);
        return cal.getTime();
    }

    public static Date getCurrentDateNoTime(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(10, 0);
        cal.set(12, 0);
        cal.set(13, 0);
        cal.set(14, 0);
        return cal.getTime();
    }

    public static String formatDate(Date date) {
        if (date == null) {
            return "";
        } else {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            return sdf.format(date);
        }
    }

    /**
     * 指定时间月的第一天
     * @param date
     * @return
     * <p>
     *     今天是 2019-07-11
     *     Date date =  new Date();
     *     return:2019-07-01 11:15:08
     * </p>
     */
    public static Date getFirstDateOfMonth(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(5, 1);
        return cal.getTime();
    }

    /**
     * 获取指定时间的月最后一天  时分秒去的是该时间的时分秒
     * @param date
     * @return
     * <p>
     *     今天是 2019-07-11
     *     Date date =  new Date();
     *     return:2019-07-31 11:15:08
     * </p>
     */
    public static Date getLastDateOfMonth(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(5, 1);
        cal.set(2, cal.get(2) + 1);
        cal.set(5, cal.get(5) - 1);
        return cal.getTime();
    }

    /**
     * 今天是 2019-07-11
     *  Date date =  new Date();
     *  return:2019-07-11 23:59:59
     * @param date
     * @return
     */
    public static Date getLastTimeOfDay(Date date) {
        LocalDateTime localDateTime = TimeConvertUtils.convertToLocalDate(date).atTime(23, 59, 59);
        return TimeConvertUtils.convertToDate(localDateTime);
    }

    /**
     * 今天是 2019-07-11
     * Date date =  new Date();
     * return:2019-07-31 00:00:00
     * @param date
     * @return
     */
    public static Date getLashDayOfMonth(Date date) {
        LocalDate localDate = TimeConvertUtils.convertToLocalDate(date);
        int length = localDate.getMonth().length(localDate.isLeapYear());
        return TimeConvertUtils.convertToDate(localDate.withDayOfMonth(length));
    }

    public static void main(String[] args) {
        System.out.println(formatDate(getLashDayOfMonth(new Date())));
        System.out.println(formatDate(getLastTimeOfDay(new Date())));
    }

    public static Date getDateByChangeMonth(Date date, int changeDlt) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(5, 15);
        cal.set(2, cal.get(2) + changeDlt);
        return cal.getTime();
    }

    public static Date getRelativeDate(Date date, int relative) {
        LOGGER.debug(formatDate(date) + " 日期调整,增量为：" + relative);
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int originMonth = cal.get(2);
        int originYear = cal.get(1);
        cal.set(2, cal.get(2) + relative);
        int dlt = Math.abs(originMonth - cal.get(2) + (originYear - cal.get(1)) * 12);
        if (dlt != Math.abs(relative)) {
            LOGGER.debug("增量之后需要调整!");
            cal.set(5, 1);
            cal.set(5, cal.get(5) - 1);
        }

        Date returnDate = cal.getTime();
        LOGGER.debug("日期调整后为：" + formatDate(returnDate));
        return returnDate;
    }

    public static String getYear(Date date) {
        if (date == null) {
            return "";
        } else {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
            return sdf.format(date);
        }
    }

    public static Date getYYYYMMDDDate(Date dt) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

        try {
            return sdf.parse(sdf.format(dt));
        } catch (ParseException var3) {
            var3.printStackTrace();
            return null;
        }
    }

    public static int getDays(Date start, Date end) {
        if (start.getTime() > end.getTime()) {
            throw new RuntimeException("开始时间必须大于结束时间!");
        } else {
            long temp = end.getTime() - start.getTime();
            return (int) (temp / 86400000L);
        }
    }

    public static int subDays(Date start, Date end) {
        long temp = end.getTime() - start.getTime();
        return (int) (temp / 86400000L);
    }

    public static int subHours(Date start, Date end) {
        long temp = end.getTime() - start.getTime();
        return (int) (temp / 3600000L);
    }

    public static String show(Date start, Date end) {
        long temp = end.getTime() - start.getTime();
        String leavingTime = temp / 86400000L + "天" + temp % 86400000L / 3600000L + "小时" + temp % 86400000L % 3600000L / 60000L + "分";
        return leavingTime;
    }

    public static Date getDateBeforeOneDay() {
        Date currentTime = new Date();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        currentTime.setDate(currentTime.getDate() - 1);
        String strDate = formatter.format(currentTime);
        ParsePosition pos = new ParsePosition(0);
        return formatter.parse(strDate, pos);
    }

    public static Date getDateYYYYMMDD(Date date, String formatType) {
        SimpleDateFormat formatter = new SimpleDateFormat(formatType);
        String strDate = formatter.format(date);
        ParsePosition pos = new ParsePosition(0);
        return formatter.parse(strDate, pos);
    }

    public static String formatDate(Date dt, String formatter) {
        SimpleDateFormat sdf = new SimpleDateFormat(formatter);
        String strDate = sdf.format(dt);
        return strDate;
    }

    public static String getCurrentDate(String format) {
        SimpleDateFormat formatter = new SimpleDateFormat(format);
        return formatter.format(Calendar.getInstance().getTime());
    }

    public static Date getSevenDaysDate(Date date) {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        date.setDate(date.getDate() + 7);
        String strDate = formatter.format(date);
        ParsePosition pos = new ParsePosition(0);
        return formatter.parse(strDate, pos);
    }

    public static Date getNDaysDate(Date date, int duration) {
        if (duration > 0) {
            date = DateUtils.addDays(date, duration - 1);
        }

        date = DateUtils.setHours(date, 23);
        date = DateUtils.setMinutes(date, 59);
        date = DateUtils.setSeconds(date, 59);
        return date;
    }

    public static Date getSevenDaysDateNoReplace(Date date) {
        try {
            SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            date.setDate(date.getDate() + 7);
            String strDate = formatter.format(date);
            ParsePosition pos = new ParsePosition(0);
            return formatter.parse(strDate, pos);
        } catch (Exception var5) {
            var5.printStackTrace();
            return date;
        }
    }

    public static Date getAfterMonth(Date date, int par) {
        return DateUtils.addMonths(date, par);
    }

    public static Date getDateyyyyMMdd() {
        Date date = new Date();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd");
        String d = formatter.format(date);
        Date r = null;

        try {
            r = formatter.parse(d);
        } catch (ParseException var5) {
            var5.printStackTrace();
        }

        return r;
    }

    public static Date getPreviousMonthDateyyyyMMdd(Date date) {
        Date r = new Date();
        r.setYear(date.getYear());
        r.setMonth(date.getMonth() - 1);
        r.setDate(date.getDate());
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd");
        String d = formatter.format(r);

        try {
            r = formatter.parse(d);
        } catch (ParseException var5) {
            var5.printStackTrace();
        }

        return r;
    }

    public static String getPreviousDayyyyyMMdd(Date date) {
        Date r = new Date();
        r.setYear(date.getYear());
        r.setMonth(date.getMonth());
        r.setDate(date.getDate() - 1);
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
        return formatter.format(r);
    }

    public static Date setDateyyyyMMDD(Date date) {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd");
        String d = formatter.format(date);
        Date r = null;

        try {
            r = formatter.parse(d);
        } catch (ParseException var5) {
            var5.printStackTrace();
        }

        return r;
    }

    public static String getTime(Date date) {
        if (date == null) {
            return "";
        } else {
            String dateformat = "yyyy-MM-dd HH:mm:ss";
            SimpleDateFormat dateFormat = new SimpleDateFormat(dateformat);
            return dateFormat.format(date);
        }
    }

    public static String getHMSTime(Date date) {
        String dateformat = "HH:mm:ss";
        SimpleDateFormat dateFormat = new SimpleDateFormat(dateformat);
        return dateFormat.format(date);
    }

    public static String getTransactionSerialNumber(String flowSeq) {
        String dateformat = "yyyyMMddHHmmssSSS";
        SimpleDateFormat dateFormat = new SimpleDateFormat(dateformat);
        if (flowSeq.length() < 3) {
            for (int i = 0; i <= 3 - flowSeq.length(); ++i) {
                flowSeq = "0".concat(flowSeq);
            }
        }

        return dateFormat.format(System.currentTimeMillis()).concat(flowSeq);
    }

    public static String getStrDate(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return sdf.format(date);
    }

    public static String getStrDate2(Date date) {
        if (date != null) {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
            return sdf.format(date);
        } else {
            return null;
        }
    }

    public static int getAge(Date birthDay) {
        Calendar cal = Calendar.getInstance();
        if (cal.before(birthDay)) {
            throw new IllegalArgumentException("The birthDay is before Now.It's unbelievable!");
        } else {
            int yearNow = cal.get(1);
            int monthNow = cal.get(2);
            int dayOfMonthNow = cal.get(5);
            cal.setTime(birthDay);
            int yearBirth = cal.get(1);
            int monthBirth = cal.get(2);
            int dayOfMonthBirth = cal.get(5);
            int age = yearNow - yearBirth;
            if (monthNow <= monthBirth) {
                if (monthNow == monthBirth) {
                    if (dayOfMonthNow < dayOfMonthBirth) {
                        --age;
                    }
                } else {
                    --age;
                }
            }

            return age;
        }
    }

    public static Date getYestodayDate() {
        Date date = new Date((new Date()).getTime() - 86400000L);
        return getDateYYYYMMDD(date, "yyyy/MM/dd");
    }

    public static String formatGMT(String d, String pattern) {
        SimpleDateFormat formatter = new SimpleDateFormat("EEE MMM d H:m:s z y", Locale.ENGLISH);

        try {
            Date date = formatter.parse(d);
            SimpleDateFormat format = new SimpleDateFormat(pattern);
            String dd = format.format(date);
            return dd;
        } catch (ParseException var6) {
            LOGGER.error("日期转化异常！dateString：" + d + " pattern:" + pattern, var6);
            return null;
        }
    }

    public static Date getFdOfCurrentMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(5, 1);
        calendar.set(11, 0);
        calendar.set(12, 0);
        calendar.set(13, 0);
        return calendar.getTime();
    }

    public static Date getLdOfCurrentMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(5, calendar.getActualMaximum(5));
        calendar.set(11, 23);
        calendar.set(12, 59);
        calendar.set(13, 59);
        return calendar.getTime();
    }

    public static Date getFdOfLastMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(2, -1);
        calendar.set(5, 1);
        calendar.set(11, 0);
        calendar.set(12, 0);
        calendar.set(13, 0);
        return calendar.getTime();
    }

    public static Date getLdOfLastMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(2, -1);
        calendar.set(5, calendar.getActualMaximum(5));
        calendar.set(11, 23);
        calendar.set(12, 59);
        calendar.set(13, 59);
        return calendar.getTime();
    }

    public static int getMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(2) + 1;
    }

    public static int getDay(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(5);
    }

    public static Date getYYYYMMString(String dtstr) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");

        try {
            return sdf.parse(dtstr);
        } catch (ParseException var3) {
            LOGGER.error("数据转换异常(自动将日期转换成默认日期：3000年1月)。错误信息：" + var3);
            return getYYYYMMString("3000-01");
        }
    }

    public static Date getYYYYMMDDString(String dtstr) throws ParseException {
        if (!StringUtils.isEmpty(dtstr)) {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            return sdf.parse(dtstr);
        } else {
            return null;
        }
    }

    public static String getYYYYMMString(Date dt) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
        return sdf.format(dt);
    }
}
